/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2007，所有权利保留。
 * 
 * 项目名：	rumba
 * 文件名：	MscbOrderMgr.java
 * 模块说明：	
 * 修改历史：
 * Oct 30, 2007 - lxm - 创建。
 */
package com.hd123.rumba.mscb.order;

import java.util.ArrayList;
import java.util.List;

import net.sf.hibernate.Hibernate;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.type.Type;

import com.hd123.rumba.domain.IDomain;
import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.log.EntityLogger;
import com.hd123.rumba.runtime.IAfterSave;
import com.hd123.rumba.runtime.IAfterSaveNew;
import com.hd123.rumba.runtime.Manager;
import com.hd123.rumba.runtime.ObserverRegistry;
import com.hd123.rumba.runtime.OperateContext;

/**
 * 消息订阅单 | 管理员 | 实现类
 * 
 * @author lxm
 * 
 */
public class MscbOrderMgr extends Manager implements IMscbOrderMgr {

  public static final String CAPTION_MANAGER = "消息订阅单管理员";

  public MscbOrderMgr() {
    super();
    this.registryClass(IMscbOrder.class.getName(), MscbOrder.class.getName());
  }

  public IMscbOrder createOrder(IDomain domain) throws BusinessException {
    this.checkParameterNotNull(domain, "domain");

    IMscbOrder order = new MscbOrder();
    order.setDomain(domain);
    order.setState(CMscbOrder.VALUE_STATE_USING);
    return order;
  }

  public IMscbOrderPrompt createPrompt(IMscbOrder order) throws BusinessException {
    this.checkParameterNotNull(order, "order");

    IMscbOrderPrompt prompt = new MscbOrderPrompt();
    prompt.setOrder(order);
    return prompt;
  }

  public void addPromptToOrder(IMscbOrder order, IMscbOrderPrompt prompt) throws BusinessException {
    this.checkParameterNotNull(order, "order");
    this.checkParameterNotNull(prompt, "prompt");

    if (order != prompt.getOrder())
      throw new BusinessException("指定的参数prompt不属于参数order。");
    if (order.getPrompts().contains(prompt))
      return;
    if (order.getPromptByProvider(prompt.getProviderClassName()) != null)
      throw new BusinessException("对于同一个" + CMscbOrder.CAPTION_CLASS + "中的提醒方式重复。");
    order.getPrompts().add(prompt);
  }

  public void removePromptFromOrder(IMscbOrder order, IMscbOrderPrompt prompt)
      throws BusinessException, HibernateException {
    this.checkParameterNotNull(order, "order");
    this.checkParameterNotNull(prompt, "prompt");
    if (!order.getPrompts().contains(prompt))
      return;
    order.getPrompts().remove(prompt);
    getSession().delete(prompt);
  }

  public void saveOrder(IMscbOrder order, OperateContext operate) throws BusinessException,
      HibernateException {
    this.checkParameterNotNull(order, "order");
    this.checkParameterNotNull(operate, "operate");

    this.verifyToSave(order);

    EntityLogger logger = new EntityLogger(this);
    logger.setEntity(order);
    logger.setEntityConstClass(CMscbOrder.class);
    logger.setOperator(operate.getOperator());
    logger.setTime(operate.getTime());

    boolean isNew = order.getUuid() == null;
    if (CMscbOrder.VALUE_STATE_USING.equals(order.getState()))
      order.setSubscribeTime(operate.getTime());
    order.setLastModified(operate.getTime());
    order.setLastModifier(operate.getOperator().getNameCode());
    getSession().saveOrUpdate(order);

    ObserverRegistry.notifyObservers(isNew ? IAfterSaveNew.class : IAfterSave.class, order);

    if (isNew)
      logger.log(EntityLogger.EVENT_ADDNEW, order.getState(), null);
    else
      logger.log(EntityLogger.EVENT_MODIFY, order.getState(), null);
  }

  public void deleteOrder(IMscbOrder order, OperateContext operate) throws BusinessException,
      HibernateException {
    this.checkParameterNotNull(order, "order");
    this.checkParameterNotNull(operate, "operate");

    EntityLogger logger = new EntityLogger(this);
    logger.setEntity(order);
    logger.setEntityConstClass(CMscbOrder.class);
    logger.setOperator(operate.getOperator());
    logger.setTime(operate.getTime());

    order.setState(CMscbOrder.VALUE_STATE_DELETED);
    order.setLastModified(operate.getTime());
    order.setLastModifier(operate.getOperator().getNameCode());
    getSession().saveOrUpdate(order);

    ObserverRegistry.notifyObservers(IAfterSave.class, order);

    logger.log(EntityLogger.EVENT_DELETE, CMscbOrder.VALUE_STATE_DELETED, null);
  }

  public IMscbOrder getOrder(String uuid) throws BusinessException, HibernateException {
    return this.getOrder(uuid, null);
  }

  public IMscbOrder getOrder(String uuid, Integer[] states) throws BusinessException,
      HibernateException {
    if (uuid == null)
      return null;
    IMscbOrder order = (IMscbOrder) getSession().load(IMscbOrder.class, uuid);
    if (states == null)
      return order;
    for (Integer s : states)
      if (s != null && s.equals(order.getState()))
        return order;
    return null;
  }

  public IMscbOrder getValidOrder(String uuid) throws BusinessException, HibernateException {
    return this.getOrder(uuid, new Integer[] {
      CMscbOrder.VALUE_STATE_USING });
  }

  public List<IMscbOrder> getValidOrdersBySubject(IDomain domain, String subjectClass, String event)
      throws BusinessException, HibernateException {
    this.checkParameterNotNull(subjectClass, "subjectClass");
    String hql = "from " + IMscbOrder.class.getName() + " o" + " where o.subjectClass = ?"
      + " and o.state <> ?";
    List params = new ArrayList();
    List<Type> types = new ArrayList<Type>();
    params.add(subjectClass);
    types.add(Hibernate.STRING);
    params.add(CMscbOrder.VALUE_STATE_DELETED);
    types.add(Hibernate.INTEGER);
    if (domain != null) {
      hql += " and o.domain.uuid = ?";
      params.add(domain.getUuid());
      types.add(Hibernate.STRING);
    }
    if (event != null) {
      hql += " and o.event = ?";
      params.add(event);
      types.add(Hibernate.STRING);
    }
    List list = getSession().find(hql, params.toArray(), (Type[]) types.toArray(new Type[] {}));
    return (List<IMscbOrder>) list;
  }

  private void verifyToSave(IMscbOrder order) throws BusinessException, HibernateException {
    if (order.getPrompts().size() == 0)
      throw new BusinessException("至少需要指定一种提醒方式。");
  }

}
